using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Threading;
using Microsoft.Practices.CompositeUI;
using Microsoft.Practices.CompositeUI.Commands;
using Microsoft.Practices.CompositeUI.UIElements;
using Microsoft.Practices.ObjectBuilder;
using SCSFContrib.CompositeUI.WPF.Activation;
using SCSFContrib.CompositeUI.WPF.BuilderStrategies;
using SCSFContrib.CompositeUI.WPF.CommandAdapters;
using SCSFContrib.CompositeUI.WPF.UIElements;
using SCSFContrib.CompositeUI.WPF.Visualizer;

namespace SCSFContrib.CompositeUI.WPF
{
	/// <summary>
	/// Extends <see cref="CabShellApplication{TWorkItem, TShell}"/> to support shell-based applications that leverage WPF.
	/// </summary>
	/// <typeparam name="TWorkItem">
	/// The type of the root application work item.
	/// </typeparam>
	/// <typeparam name="TShell">
	/// The type for the shell to use.
	/// </typeparam>
	public abstract class WindowsApplication<TWorkItem, TShell> : CabShellApplication<TWorkItem, TShell>
		where TWorkItem : WorkItem, new()
	{
		/// <summary>
		/// Constructs an instance of <c>WindowsApplication</c>.
		/// </summary>
		protected WindowsApplication()
		{
			VisualizerType = typeof(WindowsVisualizer);

			if (SynchronizationContext.Current == null)
			{
				SynchronizationContext.SetSynchronizationContext(new DispatcherSynchronizationContext());
			}
		}

		/// <summary>
		/// Adds any core builder strategies required by <c>WindowsApplication</c>s.
		/// </summary>
		/// <param name="builder">
		/// The builder to which strategies can be added.
		/// </param>
		protected override void AddBuilderStrategies(Builder builder)
		{
			base.AddBuilderStrategies(builder);
			builder.Strategies.AddNew<WindowsServiceStrategy>(BuilderStage.Initialization);
			builder.Strategies.AddNew<FrameworkElementActivationStrategy>(BuilderStage.Initialization);
			builder.Strategies.AddNew<FrameworkContentElementActivationStrategy>(BuilderStage.Initialization);
			builder.Strategies.AddNew<FrameworkElementSmartPartStrategy>(BuilderStage.Initialization);
		}

		/// <summary>
		/// Adds any core services required by <c>WindowsApplication</c>s.
		/// </summary>
		protected override void AddServices()
		{
			base.AddServices();
			RootWorkItem.Services.AddNew<FrameworkElementActivationService, IFrameworkElementActivationService>();
			RootWorkItem.Services.AddNew<FrameworkContentElementActivationService, IFrameworkContentElementActivationService>();
		}

		/// <summary>
		/// Invoked once the application shell has been created.
		/// </summary>
		protected override void AfterShellCreated()
		{
			base.AfterShellCreated();
			ICommandAdapterMapService commandAdapterMapService = RootWorkItem.Services.Get<ICommandAdapterMapService>();
			commandAdapterMapService.Register(typeof(UIElement), typeof(UIElementCommandAdapter));

			IUIElementAdapterFactoryCatalog uiElementAdapterFactoryCatalog = RootWorkItem.Services.Get<IUIElementAdapterFactoryCatalog>();
			uiElementAdapterFactoryCatalog.RegisterFactory(new ItemsControlUIAdapterFactory());
		}
	}
}